/*
 * Copyright 2011 Fabian Wenzelmann
 * 
 * This file is part of Recognition-Procedures-for-Boolean-Functions.
 * 
 * Recognition-Procedures-for-Boolean-Functions is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Recognition-Procedures-for-Boolean-Functions is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Recognition-Procedures-for-Boolean-Functions.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.wenzelmf.booleanFunction.util;

import java.io.Serializable;

/**
 * A simple class for a tuple (a, b) where a is of type A and b of type B.
 * 
 * @author Fabian Wenzelmann
 * @version 1.0
 *
 * @param <A> Type of the first component.
 * @param <B> Type of the second component.
 */
public class Tuple<A, B> implements Serializable
{
	private static final long serialVersionUID = 3374486249141010082L;
	
	/*
	 * First compoenent.
	 */
	private A first;
	
	/*
	 * Second component.
	 */
	private B second;
	
	/**
	 * Constructs a tuple representing (first, second).
	 * 
	 * @param first First component of the tuple.
	 * @param second Second component of the tuple.
	 */
	public Tuple(A first, B second)
	{
		this.first = first;
		this.second = second;
	}

	/**
	 * Returns the first component of the tuple.
	 * 
	 * @return First component of the tuple.
	 */
	public A getFirst()
	{
		return first;
	}

	/**
	 * Returns the second component of the tuple.
	 * 
	 * @return Second component of the tuple.
	 */
	public B getSecond()
	{
		return second;
	}

	/**
	 * Tests if this tuple represents the same tuple as {@code other} (of course only if {@code other}
	 * is a tuple to.
	 * 
	 * Tuple equality is defined in the following way: (a, b) = (a', b') iff a = a' and b = b'.
	 * 
	 * @return {@code true} if this equals other in the way equality is defined for tuples.
	 */
	@Override
	public boolean equals(Object other)
	{
		if(other == null)
			return false;
		if(other == this)
			return true;
		if(!(other instanceof Tuple))
			return false;
		Tuple<?, ?> otherTuple = (Tuple<?, ?>)other;
		return compareObjects(this.getFirst(), otherTuple.getFirst()) &&
			compareObjects(this.getSecond(), otherTuple.getSecond());
	}
	
	/**
	 * Internal compare method that checks for some special {@code null} cases.
	 * 
	 * @param a The first object.
	 * @param b The second object.
	 * @return {@code true} if a.equals(b) but first checks if one of the objects is {@code null}.
	 */
	private boolean compareObjects(Object a, Object b)
	{
		if(a == null)
			return b == null;
		if(b == null)
			return a == null;
		return a.equals(b);
	}
	
	/**
	 * Returns a String representation of this tuple.
	 * 
	 * @return "(a, b)" where a is the first component of this tuple and b the second.
	 */
	@Override
	public String toString()
	{
		return "(" + getFirst().toString() + ", " + getSecond().toString() + ")";
	}
	
	/**
	 * Returns a hash code for this object that is the sum of the hash codes of the two components.
	 * 
	 * @return {@code getFirst().hashCode() + getSecond().hashCode()}
	 */
	@Override
	public int hashCode()
	{
		return getFirst().hashCode() + getSecond().hashCode();
	}
	
}
